home *** CD-ROM | disk | FTP | other *** search
- From: rsalz@pineapple.bbn.com
- Newsgroups: comp.sources.misc
- Subject: v02i045: A C version of the lint driver script
- Message-ID: <7193@ncoast.UUCP>
- Date: 6 Feb 88 01:24:31 GMT
- Approved: allbery@ncoast.UUCP
-
- Comp.sources.misc: Volume 2, Issue 45
- Submitted-By: "Rich $alz" <rsalz@pineapple.BBN.COM>
- Archive-Name: lint-c-front
-
- A couple of jobs ago I worked on SysV UniSoft machines, and shell scripts
- were painfully slow. To make sure I knew pipe/fork/exec/wait semantics, I
- rewrote the lint script into C code. The games with exit and _exit helped
- shrink program size; a colleague printf/sprinf library that didn't use
- standard I/O, so this whole program was under 8K.
- As a minimum, some folks might find the transliteration of
- (/lib/cpp $O $A | $L/lint1 $X -H$H $A >>$T) 2>&1
- useful, amusing, or maybe even buggy. I know it worked back then...
-
- Enjoy,
- /r$
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'lint.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'lint.c'\"
- else
- echo shar: Extracting \"'lint.c'\" \(6486 characters\)
- sed "s/^X//" >'lint.c' <<'END_OF_FILE'
- X/*
- X** If only for hack value, a C version of the old-fashioned lint script.
- X*/
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <signal.h>
- X
- X/* Fundamental constants of the universe. */
- X#define ARG_CNT 30
- X#define TRUE 1
- X#define FALSE 0
- X
- X/* Argument lists. */
- Xchar *Lint1[ARG_CNT] = {
- X "/usr/lib/lint/lint1"
- X};
- Xint Lint1C = 1;
- X
- Xchar *Lint2[ARG_CNT] = {
- X "/usr/lib/lint/lint2"
- X};
- Xint Lint2C = 1;
- X
- Xchar *Cpp[ARG_CNT] = {
- X "/lib/cpp",
- X "-DLINT",
- X "-Dlint",
- X "-C"
- X};
- Xint CppC = 4;
- X
- X/* Other global variables. */
- Xchar Htemp[] = "/tmp/lintHXXXXXX";
- Xchar Ttemp[] = "/tmp/lintTXXXXXX";
- Xint Libstat;
- Xint Tfid;
- X
- X/* Linked in later. */
- Xextern int errno;
- Xextern char *calloc();
- Xextern char *mktemp();
- Xextern char *strcpy();
- Xextern char *strchr();
- Xextern char *strrchr();
- X/*+GETOPT ROUTINE
- X *
- X * A hacked-over version of the one in the standard library.
- X */
- X
- Xint optind = 1;
- Xchar *optarg;
- X
- Xint
- Xgetopt(ac, av, opts)
- X int ac;
- X char **av;
- X char *opts;
- X{
- X static int sp = 1;
- X register int c;
- X register char *cp;
- X
- X if (sp == 1)
- X if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0')
- X return('\0');
- X else if (strcmp(av[optind], "--") == 0)
- X {
- X optind++;
- X return('\0');
- X }
- X
- X c = av[optind][sp];
- X if (c == ':' || (cp = strchr(opts, c)) == NULL)
- X yelp("illegal option \"%c\"", c);
- X if (*++cp == ':')
- X {
- X if (av[optind][sp + 1] != '\0')
- X optarg = &av[optind++][sp + 1];
- X else if (++optind >= ac)
- X yelp("option \"%c\" requires an argument", c);
- X else
- X optarg = av[optind++];
- X sp = 1;
- X }
- X else
- X {
- X if (av[optind][++sp] == '\0')
- X {
- X sp = 1;
- X optind++;
- X }
- X optarg = NULL;
- X }
- X return(c);
- X}
- X/*+SIGNAL CATCHERS AND EXITS
- X */
- X
- X
- X#ifdef LINT
- Xextern void exit();
- X#else
- Xexit(X) int X; { _exit(X); }
- X#endif LINT
- X
- X
- X/* VARARGS1 */
- Xyelp(A, B)
- X char *A;
- X char *B;
- X{
- X int E;
- X
- X E = errno;
- X printf(A, B);
- X printf(" (errno = %d).\n", E);
- X exit(1);
- X}
- X
- X
- XRupt()
- X{
- X (void)unlink(Htemp);
- X (void)unlink(Ttemp);
- X yelp("\r\nInterrupted!\r\n");
- X /* NOTREACHED */
- X}
- X/*+UTILITY ROUTINES
- X */
- X
- X
- X/*
- X * This routine appends a lint library to the T file.
- X */
- XLib(N, Flag)
- X char *N;
- X int Flag;
- X{
- X register int F;
- X register int i;
- X char Buff[BUFSIZ];
- X
- X if (Flag)
- X sprintf(Buff, "/usr/lib/lint/llib-l%s.ln", N);
- X else
- X (void)strcpy(Buff, N);
- X
- X if ((F = open(Buff, O_RDONLY)) < 0)
- X printf("cannot open \"%s\" lint library (errno=%d)", Buff, errno);
- X else
- X {
- X while ((i = read(F, Buff, sizeof Buff)) > 0)
- X (void)write(Tfid, Buff, (unsigned int)i);
- X (void)close(F);
- X }
- X}
- X
- X
- X/*
- X * This routine concats an argument to an arglist, perhaps preceeding
- X * it with a minus sign and a letter.
- X */
- XAdd(C, Alist, Arg, Simple)
- X int C;
- X char **Alist;
- X char *Arg;
- X char Simple;
- X{
- X int L;
- X register char *p;
- X
- X if (C >= ARG_CNT - 2)
- X yelp("too many arguments");
- X /* NOTREACHED */
- X
- X L = strlen(Arg) + 1;
- X if (Simple)
- X L += 2;
- X p = Alist[C] = calloc((unsigned int)L, 1);
- X if (Simple)
- X {
- X *p++ = '-';
- X *p++ = Simple;
- X }
- X (void)strcpy(p, Arg);
- X}
- X/*!*/
- X/*
- X * This routine is implements this line from the script:
- X * (/lib/cpp $O $A | $L/lint1 $X -H$H $A >>$T) 2>&1
- X */
- XDo(N)
- X char *N;
- X{
- X int P[2];
- X
- X if (fork() == 0)
- X {
- X /* The kids run "... 2>&1" */
- X (void)close(2);
- X (void)dup(1);
- X (void)pipe(P);
- X
- X Cpp[CppC] = N;
- X Lint1[Lint1C] = N;
- X
- X if (fork() == 0)
- X {
- X /* Younger child runs "cpp | ..." */
- X (void)close(1);
- X (void)dup(P[1]);
- X (void)close(P[1]);
- X (void)close(P[0]);
- X (void)close(Tfid);
- X (void)execv(Cpp[0], Cpp);
- X yelp("No cpp?");
- X /* NOTREACHED */
- X }
- X else
- X {
- X /* Older child runs "... | lint >> Tfid" */
- X (void)close(0);
- X (void)dup(P[0]);
- X (void)close(P[0]);
- X (void)close(P[1]);
- X (void)close(1);
- X (void)dup(Tfid);
- X (void)close(Tfid);
- X (void)execv(Lint1[0], Lint1);
- X yelp("No lint1?");
- X /* NOTREACHED */
- X }
- X }
- X else
- X (void)wait((int *)0);
- X}
- X/*+MAIN ROUTINE
- X */
- X
- X
- Xmain(ac, av)
- X register int ac;
- X register char *av[];
- X{
- X register char *p;
- X register int c;
- X struct stat Sb;
- X
- X (void)mktemp(Htemp);
- X (void)mktemp(Ttemp);
- X Tfid = open(Ttemp, O_RDWR | O_CREAT | O_APPEND, 0666);
- X Add(Lint2C++, Lint2, Ttemp, 'T');
- X
- X /* Parse JCL. */
- X while (c = getopt(ac, av, "abhuvxI:D:U:Nnpl:o:"))
- X switch (c)
- X {
- X /* [abhuvx] -- standard lint flags. */
- X case 'a': case 'b': case 'h': case 'u': case 'v': case 'x':
- X Add(Lint1C++, Lint1, "", c);
- X Add(Lint2C++, Lint2, "", c);
- X break;
- X /* [DIU] -- standard cpp flags. */
- X case 'D': case 'I': case 'U':
- X Add(CppC++, Cpp, optarg, c);
- X break;
- X /* p -- portable library. */
- X case 'p':
- X Add(Lint1C++, Lint1, "", c);
- X Add(Lint2C++, Lint1, "", c);
- X /* [Nn] -- net or no library. */
- X case 'N': case 'n':
- X Libstat = c;
- X break;
- X /* l -- lint library. */
- X case 'l':
- X Lib(optarg, TRUE);
- X break;
- X /* o -- output file (redirection without meta chars). */
- X case 'o':
- X (void)close(1);
- X (void)open(optarg, O_WRONLY | O_CREAT | O_TRUNC, 0666);
- X break;
- X }
- X
- X Add(Lint1C++, Lint1, Htemp, 'H');
- X Add(Lint2C++, Lint2, Htemp, 'H');
- X if (signal(SIGINT, SIG_IGN) != SIG_IGN)
- X (void)signal(SIGINT, Rupt);
- X
- X /* Did flags; do filenames and libraries. */
- X for (; optind < ac; optind++)
- X {
- X /* Check for -l.. argument. */
- X if (*(p = av[optind]) == '-' && *++p == 'l')
- X {
- X Lib(++p, TRUE);
- X continue;
- X }
- X
- X /* Check for *.c for *.ln arguments. */
- X if (p = strrchr(av[optind], '.'))
- X {
- X if (*++p == 'c' && p[1] == '\0')
- X {
- X Do(av[optind]);
- X continue;
- X }
- X if (p[0] == 'l' && p[1] == 'n' && p[2] == '\0')
- X {
- X Lib(av[optind], FALSE);
- X continue;
- X }
- X }
- X printf("Not grokked -- \"%s\" -- ignored\n", av[optind]);
- X }
- X
- X /* Any standard C library? */
- X switch (Libstat)
- X {
- X case '\0': Lib("c", TRUE); break;
- X case 'N': Lib("netc", TRUE);
- X Lib("net", TRUE); break;
- X case 'p': Lib("port", TRUE); break;
- X }
- X
- X (void)close(Tfid);
- X
- X /* If lint1 created anything, run lint2. */
- X if (stat(Htemp, &Sb) >= 0 && Sb.st_size >= 0)
- X {
- X Add(Lint2C, Lint2, Htemp, 'H');
- X if (fork() == 0)
- X {
- X (void)execv(Lint2[0], Lint2);
- X yelp("No lint2?");
- X /* NOTREACHED */
- X }
- X (void)wait((int *)0);
- X }
- X
- X /* That's all she wrote. */
- X (void)unlink(Htemp);
- X (void)unlink(Ttemp);
- X exit(0);
- X}
- END_OF_FILE
- if test 6486 -ne `wc -c <'lint.c'`; then
- echo shar: \"'lint.c'\" unpacked with wrong size!
- fi
- # end of 'lint.c'
- fi
- echo shar: End of shell archive.
- exit 0
-